package com.demo.gulimall.search.thread;

import java.util.concurrent.*;

/**
 * JUC 测试
 * @author Chen Yuan
 * @create 2023-06-09  9:49
 */
public class ThreadTest {

	// 自定义线程池, 创建10个线程的线程池
	public static ExecutorService executorService = Executors.newFixedThreadPool(10);


	public static void main(String[] args) {
		System.out.println("======== main --- start --------");
		// 启动一个异步任务, 并使用指定的线程池->executorService

// 1. 使用 runAsync
		//CompletableFuture.runAsync(()->{
		//	threadTestBody();
		//}, executorService);

// 2. 使用 supplyAsync
		// 2.1 Complete 相关
		//CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
		//	int i = threadTestBody();
		//	return i;
		//}, executorService).whenComplete((res, exc) -> {
		//	System.out.println("--- 异步任务执行完成 -- 结果:" + res + ", 异常: " + exc);
		//}).exceptionally(throwable -> {
		//	// 可以感知异常, 同时返回默认结果
		//	return -1;
		//});


		// 2.1 handle 相关
		//CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
		//	int i = threadTestBody();
		//	return i;
		//}, executorService).handle((res, exc) -> {
		//	// 可以获取返回结果、获取异常、并对返回结果进行处理
		//	if (null != res) {
		//		return (res * 10);
		//	}
		//	if (null != exc) {
		//		return -1;
		//	}
		//	return 0;
		//});

// 3. 线程串行化, A执行完接着执行B
		// 3.1 thenRun: 不能获取到上一步的执行结果
		//CompletableFuture.supplyAsync(() -> {
		//	System.out.println("--- 任务 A 启动了");
		//	int i = threadTestBody();
		//	return i;
		//}, executorService).thenRunAsync(() -> {
		//	System.out.println("--- 任务 B 启动了");
		//}, executorService);

		// 3.2 thenAccept: 可以获取到上一步的执行结果, 但是没有返回值
		//CompletableFuture.supplyAsync(() -> {
		//	System.out.println("--- 任务 A 启动了");
		//	int i = threadTestBody();
		//	return i;
		//}, executorService).thenAcceptAsync((res) -> {
		//	System.out.println("--- 任务 B 启动了, 上一步的结果: " + res);
		//}, executorService);

		// 3.3  thenApply: 可以获取到上一步的执行结果, 并且可以返回自己的结果
		//CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
		//	System.out.println("--- 任务 A 启动了");
		//	int i = threadTestBody();
		//	return i;
		//}, executorService).thenApplyAsync((res) -> {
		//	System.out.println("--- 任务 B 启动了, 上一步的结果: " + res);
		//
		//	return "上一步的结果: " + res;
		//}, executorService);

// 4. 两个任务组合 - 两个任务都要完成

		//CompletableFuture<Object> futureA = CompletableFuture.supplyAsync(() -> {
		//	System.out.println("--- 任务 A 启动了");
		//	System.out.println("--- 任务 A 完成了");
		//	return 1;
		//}, executorService);
		//CompletableFuture<Object> futureB = CompletableFuture.supplyAsync(() -> {
		//	System.out.println("--- 任务 B 启动了");
		//	try {
		//		Thread.sleep(3000);
		//		System.out.println("--- 任务 B 完成了");
		//	} catch (InterruptedException e) {
		//		e.printStackTrace();
		//	}
		//	return "任务B";
		//}, executorService);
		//CompletableFuture<Object> futureC = CompletableFuture.supplyAsync(() -> {
		//	System.out.println("--- 任务 C 启动了");
		//	try {
		//		Thread.sleep(5000);
		//		System.out.println("--- 任务 C 完成了");
		//	} catch (InterruptedException e) {
		//		e.printStackTrace();
		//	}
		//	return "任务C";
		//}, executorService);

		// 4.1 runAfterBothAsync: 不能获取前两个任务的结果
		//futureA.runAfterBothAsync(futureB, () -> {
		//	System.out.println("--- 任务 C 启动了");
		//}, executorService);

		// 4.2 thenAcceptBothAsync: 可以获取到前两个任务的结果, 但没有返回值
		//futureA.thenAcceptBothAsync(futureB, (res1, res2)->{
		//	System.out.println("--- 任务 C 启动了 - futureA: " + res1 + ", futureB: " + res2);
		//}, executorService);

		// 4.3 thenCombineAsync: 可以获取到前两个任务的结果, 且有返回值
		//CompletableFuture<String> future = futureA.thenCombineAsync(futureB, (res1, res2) -> {
		//	String res = "futureA: " + res1 + ", futureB: " + res2;
		//	System.out.println("--- 任务 C 启动了 - " + res);
		//	return res;
		//}, executorService);


// 5. 两个任务组合 - 其中一个任务完成就继续执行

		// 5.1 runAfterEitherAsync: 获取不到前两个任务的返回值
		//futureA.runAfterEitherAsync(futureB, ()->{
		//	System.out.println("--- 任务 C 启动了");
		//}, executorService);

		// 5.2 runAfterEitherAsync: 可以获取到前两个线程之一的返回结果, 但自己不返回
		//futureA.acceptEitherAsync(futureB, (res)->{
		//	System.out.println("--- 任务 C 启动了 - futureA 或 futureB 的结果: " + res);
		//}, executorService);

		// 5.2 applyToEitherAsync: 可以获取到前两个线程之一的返回结果, 且自己有返回值
		//CompletableFuture<String> future = futureA.applyToEitherAsync(futureB, (res) -> {
		//	String result = "futureA 或 futureB 的结果" + res;
		//	System.out.println("--- 任务 C 启动了 - " + result);
		//	return result;
		//}, executorService);

// 6. 多任务组合

		// 6.1 多个任务全部执行完成
		//CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(futureA, futureB, futureC);
		//try {
		//	allOfFuture.get();
		//	System.out.println("--- allOfFuture ---");
		//} catch (Exception e) {
		//	e.printStackTrace();
		//}

		// 6.2 多个任务, 任意一个完成即可, 并且可以获取第一个成功的线程的结果
		//CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(futureA, futureB, futureC);
		//try {
		//	Object firstRes = anyOfFuture.get();
		//	System.out.println("--- anyOfFuture --- firstRes: " + firstRes);
		//} catch (Exception e) {
		//	e.printStackTrace();
		//}


		//try {
		//	System.out.println("--- future: " + future.get());
		//} catch (Exception e) {
		//	e.printStackTrace();
		//}

		System.out.println("======== main --- end --------");
	}

	private static int threadTestBody() {
		System.out.println("--- 当前线程: " + Thread.currentThread().getId());
		int i = 10 / 2;
		System.out.println("--- 运行结果: " + i);
		return i;
	}
}
